package com.vichat.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.vichat.common.cache.RedisHelper;
import com.vichat.common.constant.GlobalConstant;
import com.vichat.common.util.NumberUtils;
import com.vichat.common.vo.PageFilter;
import com.vichat.core.dao.BaseDaoI;
import com.vichat.user.entity.*;
import com.vichat.user.service.IAgentSecService;
import com.vichat.user.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by user on 2017/11/15.
 */
@Service("agentSecService")
public class AgentSecServiceImpl implements IAgentSecService {
    protected static final Logger logger = LoggerFactory.getLogger(AgentSecServiceImpl.class);
    @Autowired
    private BaseDaoI<AgentSecRole> agentSecRoleDao;
    @Autowired
    private BaseDaoI<AgentSecFunction> agentSecFuncDao;
    @Autowired
    private BaseDaoI<AgentSecRoleFunction> agentSecRoleFunctionDao;
    @Autowired
    private BaseDaoI<AgentUserSecRoleRel> agentUserSecRoleRelDao;

    /**
     * 拼装排序字段
     *
     * @param pf
     * @return
     */
    private String orderHql(PageFilter pf) {
        String orderString = "";
        if (pf != null) {
            if ((pf.getSort() != null) && (pf.getOrder() != null)) {
                orderString = " order by " + pf.getSort() + " " + pf.getOrder();
            }
        }
        return orderString;
    }

    /**
     * 查询角色信息
     *
     * @param queryBean
     * @param pf
     * @return
     */
    public List<AgentSecRole> querySecRole(AgentSecRole queryBean, PageFilter pf) {
        HashMap params = new HashMap();
        String hql = "from AgentSecRole where  state=1  ";
        if (NumberUtils.isNotNullOrZero(queryBean.getRoid())) {
            hql += " and roid = :roid";
            params.put("roid", queryBean.getRoid());
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getAgentId())) {
            hql += " and agentId like :agentId";
            params.put("agentId", queryBean.getAgentId());
        }
        if (StringUtils.isNotBlank(queryBean.getRoleName())) {
            hql += " and roleName like :roleName";
            params.put("roleName", "%" + queryBean.getRoleName() + "%");
        }

        List<AgentSecRole> secRoles = agentSecRoleDao.find(hql + orderHql(pf), params, pf.getPage(), pf.getLimit());
        return secRoles;
    }

    /**
     * 查询角色信息（无参数）
     *
     * @return
     */
    public List<AgentSecRole> querySecRole() {
        HashMap params = new HashMap();
        String hql = "from AgentSecRole where  state=1  ";
        hql += " order by roid";

        List<AgentSecRole> secRoles = agentSecRoleDao.find(hql, params);
        return secRoles;
    }

    /**
     * 查询角色数量
     *
     * @param queryBean
     * @return
     * @throws Exception
     */
    public Long countSecRole(AgentSecRole queryBean) throws Exception {
        Map<String, Object> params = new HashMap<String, Object>();
        String hql = "select count(*) from AgentSecRole where state = 1";
        if (NumberUtils.isNotNullOrZero(queryBean.getRoid())) {
            hql += " and roid like :roid";
            params.put("roid", "%" + queryBean.getRoid() + "%");
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getAgentId())) {
            hql += " and agentId like :agentId";
            params.put("agentId", queryBean.getAgentId());
        }
        if (StringUtils.isNotBlank(queryBean.getRoleName())) {
            hql += " and roleName like :roleName";
            params.put("roleName", "%" + queryBean.getRoleName() + "%");
        }
        return agentSecRoleDao.count(hql, params);
    }

    /**
     * 根据角色编号获取角色信息
     *
     * @param roid
     * @return
     */
    public AgentSecRole querySecRoleByRoid(long roid) {
        AgentSecRole secRoleFDB = null;
        String jsonStr = RedisHelper.getAgentSecRole(roid);
        if (StringUtils.isNotBlank(jsonStr)) {
            secRoleFDB = JSONObject.parseObject(jsonStr, AgentSecRole.class);
        } else {
            if (NumberUtils.isNotNullOrZero(roid)) {
                secRoleFDB = agentSecRoleDao.get(AgentSecRole.class, roid);
                if (secRoleFDB != null)
                    RedisHelper.setAgentSecRole(secRoleFDB.getRoid(), JSONObject.toJSONString(secRoleFDB));
            }
        }
        return secRoleFDB;
    }

    /**
     * 根据角色编号删除角色
     *
     * @param roid
     */
    public void delSecRole(long roid) {
        AgentSecRole secRoleFDB = this.querySecRoleByRoid(roid);
        if (secRoleFDB != null) {
            agentSecRoleDao.deleted(secRoleFDB);
            RedisHelper.delAgentSecRole(roid);
        }
    }

    /**
     * 添加或者修改角色
     *
     * @param secRole
     * @throws Exception
     */
    @Override
    public void saveOrUpdSecRole(AgentSecRole secRole) throws Exception {
        AgentSecRole secRoleFDB = this.querySecRoleByRoid(secRole.getRoid());
        if (secRoleFDB == null) {
            agentSecRoleDao.save(secRole);
            RedisHelper.setAgentSecRole(secRole.getRoid(), JSONObject.toJSONString(secRole));
        } else {
            secRoleFDB.setRoid(secRole.getRoid());
            secRoleFDB.setRoleName(secRole.getRoleName());
            secRoleFDB.setRoleDesc(secRole.getRoleDesc());
            agentSecRoleDao.update(secRoleFDB);
            RedisHelper.setAgentSecRole(secRole.getRoid(), JSONObject.toJSONString(secRoleFDB));
        }
    }

    /**
     * 查询菜单信息
     * 无参数
     *
     * @return
     */
    public List<AgentSecFunction> querySecFunction() {
        HashMap params = new HashMap();
        String hql = "from AgentSecFunction where  state=1  ";
        hql += " order by sortno";

        List<AgentSecFunction> secFuncs = agentSecFuncDao.find(hql, params);
        return secFuncs;
    }

    /**
     * 查询菜单信息
     *
     * @param queryBean
     * @param pf
     * @return
     */
    public List<AgentSecFunction> querySecFunction(AgentSecFunction queryBean, PageFilter pf) {
        HashMap params = new HashMap();
        String hql = "from AgentSecFunction where  state=1  ";
        if (NumberUtils.isNotNullOrZero(queryBean.getFid())) {
            hql += " and fid like :fid";
            params.put("fid", "%" + queryBean.getFid() + "%");
        }
        if (StringUtils.isNotBlank(queryBean.getFuncName())) {
            hql += " and funcName like :funcName";
            params.put("funcName", "%" + queryBean.getFuncName() + "%");
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getParentFid())) {
            hql += " and ( parentFid = :parentFid or fid =:parentFid)";
            params.put("parentFid", queryBean.getParentFid());
        }
        List<AgentSecFunction> secFuncs = agentSecFuncDao.find(hql + orderHql(pf), params, pf.getPage(), pf.getRows());
        return secFuncs;
    }

    /**
     * 查询菜单数量
     *
     * @param queryBean
     * @return
     * @throws Exception
     */

    public Long countSecFunction(AgentSecFunction queryBean) throws Exception {
        Map<String, Object> params = new HashMap<String, Object>();
        String hql = "select count(*) from AgentSecFunction where state = 1";
        if (NumberUtils.isNotNullOrZero(queryBean.getFid())) {
            hql += " and fid like :fid";
            params.put("fid", "%" + queryBean.getFid() + "%");
        }
        if (StringUtils.isNotBlank(queryBean.getFuncName())) {
            hql += " and funcName like :funcName";
            params.put("funcName", "%" + queryBean.getFuncName() + "%");
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getParentFid())) {
            hql += " and ( parentFid = :parentFid or fid =:parentFid)";
            params.put("parentFid", queryBean.getParentFid());
        }
        return agentSecFuncDao.count(hql, params);
    }

    /**
     * 根据菜单编号获取菜单信息
     *
     * @param fid
     * @return
     */
    public AgentSecFunction querySecFuncByFid(long fid) {
        AgentSecFunction secFuncFDB = null;
        String jsonStr = RedisHelper.getAgentSecFunc(fid);
        if (StringUtils.isNotBlank(jsonStr)) {
            secFuncFDB = JSONObject.parseObject(jsonStr, AgentSecFunction.class);
        } else {
            if (NumberUtils.isNotNullOrZero(fid)) {
                secFuncFDB = agentSecFuncDao.get(AgentSecFunction.class, fid);
                RedisHelper.setAgentSecFunc(secFuncFDB.getFid(), JSONObject.toJSONString(secFuncFDB));
            }
        }
        return secFuncFDB;
    }

    /**
     * 根据角色编号获取菜单分配信息
     *
     * @param uid
     * @return
     */
    public List<AgentSecRoleFuncVO> querySecRoleFuncVOByUid(long uid) {
        List<AgentSecRoleFuncVO> secRoleFuncVOS = new ArrayList<AgentSecRoleFuncVO>();//分配菜单数据集合
        AgentSecRoleFuncVO secRoleFuncVO = null;
        HashMap params = new HashMap();

        List<AgentSecRoleFunction> secRoleFunctions = null;
        String sql = "select a.* from ccsdb.agent_sec_role_function a,ccsdb.agent_user b,ccsdb.agent_user_sec_role_rel c where  a.state=1 and  a.roid = c.roid and b.agent_uid = c.agent_uid";
        if (NumberUtils.isNotNullOrZero(uid)) {
            sql += " and b.agent_uid = :uid";
            params.put("uid", uid);
        }
        sql += " order by a.roid, a.fid";
        secRoleFunctions = agentSecRoleFunctionDao.findEntityBySql(sql, params, AgentSecRoleFunction.class);
        //获取一级菜单信息
        String hql = "from AgentSecFunction where  funcType = 1 and state=1 and funcLevel =1 order by sortno";
        List<AgentSecFunction> secFirstFunctions = agentSecFuncDao.find(hql);
        //获取二级菜单信息
        hql = "from AgentSecFunction where funcType = 1 and  state=1 and funcLevel =2 order by sortno";
        List<AgentSecFunction> secSecondFunctions = agentSecFuncDao.find(hql);
        List<AgentSecFunction> secFuncSeconds = null;
        if (secFirstFunctions != null) {//一级菜单数据非空
            for (AgentSecFunction secFirstFunction : secFirstFunctions) {//遍历一级菜单
                secRoleFuncVO = new AgentSecRoleFuncVO();
                for (AgentSecRoleFunction secRoleFunction : secRoleFunctions) {//遍历一级菜单勾选数据
                    if (secRoleFunction.getFid().intValue() == secFirstFunction.getFid().intValue()) {
                        secFirstFunction.setIsChecked(true);
                        break;
                    }
                }
                secRoleFuncVO.setFristFunc(secFirstFunction);
                if (secSecondFunctions != null) {//二级菜单数据非空
                    secFuncSeconds = new ArrayList<>();
                    for (AgentSecFunction secSecondFunction : secSecondFunctions) {//遍历二级菜单数据
                        if (secFirstFunction.getFid().intValue() == secSecondFunction.getParentFid().intValue()) {//根据一级菜单编号筛选相关的二级菜单数据
                            for (AgentSecRoleFunction secRoleFunction : secRoleFunctions) {//遍历二级菜单勾选数据
                                if (secRoleFunction.getFid().intValue() == secSecondFunction.getFid().intValue()) {
                                    secSecondFunction.setIsChecked(true);
                                    break;
                                }
                            }
                            secFuncSeconds.add(secSecondFunction);
                        }
                    }
                    secRoleFuncVO.setSecondFuncList(secFuncSeconds);
                }
                secRoleFuncVOS.add(secRoleFuncVO);
            }
        }
        return secRoleFuncVOS;
    }

    /**
     * 根据角色编号获取菜单分配信息
     *
     * @param roid
     * @return
     */
    public List<AgentSecFunction> querySecRoleFuncVOByRoid(long roid) {
        HashMap params = new HashMap();
        String hql = "";

        List<AgentSecRoleFunction> secRoleFunctions = null;
        hql = "from AgentSecRoleFunction where  state=1  ";
        if (NumberUtils.isNotNullOrZero(roid)) {
            hql += " and roid = :roid";
            params.put("roid", roid);
        }
        hql += " order by roid, fid";
        secRoleFunctions = agentSecRoleFunctionDao.find(hql, params);
        //获取一级菜单信息
        hql = "from AgentSecFunction where  state=1 order by sortno";
        List<AgentSecFunction> secFirstFunctions = agentSecFuncDao.find(hql);
        if (secFirstFunctions != null) {//一级菜单数据非空
            for (AgentSecFunction secFirstFunction : secFirstFunctions) {//遍历一级菜单
                for (AgentSecRoleFunction secRoleFunction : secRoleFunctions) {//遍历一级菜单勾选数据
                    if (secRoleFunction.getFid().intValue() == secFirstFunction.getFid().intValue()) {
                        secFirstFunction.setIsChecked(true);
                        break;
                    }
                }
            }
        }
        return secFirstFunctions;
    }

    /**
     * 根据角色编号获取已勾选菜单信息
     *
     * @param roid
     * @return
     */
    public List<AgentSecRoleFunction> querySecRoleFunctionByRoid(long roid) {
        List<AgentSecRoleFunction> secRoleFuncFDBs = null;
        String jsonStr = RedisHelper.getAgentSecRoleFunc(roid);
        if (StringUtils.isNotBlank(jsonStr)) {
            secRoleFuncFDBs = JSONObject.parseArray(jsonStr, AgentSecRoleFunction.class);//获取所有已勾选的菜单
        } else {
            HashMap params = new HashMap();
            String hql = "from AgentSecRoleFunction where  state=1  ";
            if (NumberUtils.isNotNullOrZero(roid)) {
                hql += " and roid = :roid";
                params.put("roid", roid);
            }
            hql += " order by roid, fid";
            secRoleFuncFDBs = agentSecRoleFunctionDao.find(hql, params);
        }
        return secRoleFuncFDBs;
    }

    /**
     * 增加角色名称校验
     */
    public boolean repeatSecRole(AgentSecRole queryBean) {
        Map<String, Object> params = new HashMap<String, Object>();
        String hql = "select count(*) from AgentSecRole where 1 = 1";
        if (NumberUtils.isNotNullOrZero(queryBean.getRoid())) {
            hql += " and roid <>:roid";
            params.put("roid", queryBean.getRoid());
        }
        if (StringUtils.isNotBlank(queryBean.getRoleName())) {
            hql += " and roleName =:roleName";
            params.put("roleName", queryBean.getRoleName());
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getAgentId())) {
            hql += " and agentId =:agentId";
            params.put("agentId", queryBean.getAgentId());
        }
        long count = agentSecRoleDao.count(hql, params);
        if (count < 1) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void saveSecRoleFunction(RoleMenuVO roleMenuVO) {
        Long roleId = Long.parseLong(roleMenuVO.getRoleId());
        String hql = "delete from AgentSecRoleFunction where state=1 and roid=" + roleId;
        if (agentSecRoleFunctionDao.executeHql(hql) > 0) {
            RedisHelper.delAgentSecRoleFunc(roleId);
        }
        for (String str : roleMenuVO.getList()) {
            AgentSecRoleFunction secRoleFunction = new AgentSecRoleFunction();
            secRoleFunction.setRoid(roleId);
            secRoleFunction.setFid(Long.parseLong(str));
            agentSecRoleFunctionDao.save(secRoleFunction);
        }

        List<AgentSecRoleFunction> secRoleFuncFDBs = new ArrayList<AgentSecRoleFunction>();
        //遍历菜单时用以保存的对象
        AgentSecRoleFunction secRoleFunction = null;
        List<PrivilegeVO> privilegeVOS = new ArrayList<>();//左侧菜单
        //获取一级菜单信息
        List<AgentSecFunction> secFirstFunctions = getMenus(GlobalConstant.SEC_FUN_LEVEL_1, null);
        for (AgentSecFunction secFunction : secFirstFunctions) {
            // 保存一级菜单中勾选的数据 start
            secRoleFunction = new AgentSecRoleFunction();
            secRoleFunction.setRoid(roleId);
            secRoleFunction.setFid(secFunction.getFid());
            secRoleFuncFDBs.add(secRoleFunction);

            // 保存一级菜单中勾选的数据用做左侧菜单 start
            PrivilegeVO privilegeVO = new PrivilegeVO();
            AgentSecFunction funcNameOther = querySecFuncByFid(secFunction.getFid());
            privilegeVO.setTitle(funcNameOther.getFuncName());
            privilegeVO.setIcon(funcNameOther.getFuncPic());
            privilegeVO.setHref(funcNameOther.getFuncUrl());
            privilegeVO.setSpread(false);

            List<Privilege> privilegeSeconds = new ArrayList<>();
            //获取二级菜单信息
            List<AgentSecFunction> secSecondFunctions = getMenus(GlobalConstant.SEC_FUN_LEVEL_2, secFunction.getFid());
            for (AgentSecFunction secondFunc : secSecondFunctions) {
                // 保存二级菜单中勾选的数据 start
                secRoleFunction = new AgentSecRoleFunction();
                secRoleFunction.setRoid(roleId);
                secRoleFunction.setFid(secondFunc.getFid());

                // 保存二级菜单中勾选的数据用做左侧菜单 start
                Privilege privilegeSecond = new Privilege();
                funcNameOther = querySecFuncByFid(secondFunc.getFid());
                privilegeSecond.setTitle(funcNameOther.getFuncName());
                privilegeSecond.setIcon(funcNameOther.getFuncPic());
                privilegeSecond.setHref(funcNameOther.getFuncUrl());
                privilegeSecond.setSpread(false);
                privilegeSeconds.add(privilegeSecond);//二级菜单赋值
            }
            if (!privilegeSeconds.isEmpty()) {
                privilegeVO.setChildren(privilegeSeconds);
            }
            privilegeVOS.add(privilegeVO);

        }
        RedisHelper.setAgentSecRoleFunc(roleId, JSONObject.toJSONString(secRoleFuncFDBs));
        RedisHelper.setAgentSecPrivilege(roleId, JSONObject.toJSONString(privilegeVOS));
    }

    /**
     * @param
     * @return
     * @throws
     * @Title: getMenus
     * @Description: 获取菜单数据根据级别
     */
    public List<AgentSecFunction> getMenus(Long funcLevel, Long parentFid) {
        HashMap params = new HashMap();
        String hql = "from AgentSecFunction where state=1 ";
        if (funcLevel != null) {
            hql += " and funcLevel =:funcLevel";
            params.put("funcLevel", funcLevel);
        }
        if (parentFid != null) {
            hql += " and parentFid =:parentFid";
            params.put("parentFid", parentFid);
        }
        hql += " order by sortno";
        return agentSecFuncDao.find(hql, params);
    }

    /**
     * 根据角色编号查询菜单
     *
     * @param uid
     * @return
     */
    public List<PrivilegeVO> querySecPrivilege(long uid) {
        List<PrivilegeVO> privilegeVOS = new ArrayList<>();
        List<AgentSecRoleFuncVO> secRoleFuncVOS = this.querySecRoleFuncVOByUid((int) uid);//获取所有菜单

        if (!secRoleFuncVOS.isEmpty()) {
            for (AgentSecRoleFuncVO secRoleFuncVO : secRoleFuncVOS) {//循环一级菜单
                if (secRoleFuncVO == null || secRoleFuncVO.getFristFunc() == null) continue;
                AgentSecFunction secFirst = secRoleFuncVO.getFristFunc();
                if (secFirst == null || !secFirst.getIsChecked()) continue;//一级有权限则赋值，否则跳到下一条
                PrivilegeVO privilegeVO = new PrivilegeVO();
                privilegeVO.setTitle(secFirst.getFuncName());
                privilegeVO.setIcon(secFirst.getFuncPic());
                privilegeVO.setHref(secFirst.getFuncUrl());
                privilegeVO.setName(secFirst.getFuncDesc());
                privilegeVO.setSpread(false);

                if (!secRoleFuncVO.getSecondFuncList().isEmpty()) {
                    List<AgentSecFunction> secSeconds = secRoleFuncVO.getSecondFuncList();
                    List<Privilege> privilegeSeconds = new ArrayList<>();
                    for (AgentSecFunction secSecond : secSeconds) {//循环二级菜单
                        if (secSecond == null || !secSecond.getIsChecked()) continue;//二级有权限则赋值，否则跳到下一条
                        Privilege privilegeSecond = new Privilege();
                        privilegeSecond.setTitle(secSecond.getFuncName());
                        privilegeSecond.setIcon(secSecond.getFuncPic());
                        privilegeSecond.setHref(secSecond.getFuncUrl());
                        privilegeSecond.setName(secSecond.getFuncDesc());
                        privilegeSecond.setSpread(false);
                        privilegeSeconds.add(privilegeSecond);//二级菜单赋值
                    }
                    if (!privilegeSeconds.isEmpty()) {
                        privilegeVO.setChildren(privilegeSeconds);
                    }
                }
                privilegeVOS.add(privilegeVO);
            }
            RedisHelper.setAgentSecPrivilege(uid, JSONObject.toJSONString(privilegeVOS));
        }
        return privilegeVOS;
    }

    /**
     * 根据条件查询角色信息
     *
     * @param uid
     * @return
     */
    public AgentSecRole querySecRoleByUid(Long uid) {
        String sql = "select a.* from ccsdb.agent_sec_role a, ccsdb.agent_user_sec_role_rel b where a.roid = b.roid and b.agent_uid = :uid";
        HashMap params = new HashMap();
        params.put("uid", uid);
        List<AgentSecRole> secRoleList = agentSecRoleDao.findEntityBySql(sql, params, AgentSecRole.class);
        if (secRoleList != null && secRoleList.size() > 0) {
            return secRoleList.get(0);
        }
        return null;
    }

    public void saveUserSecRoleRel(Long uid, Long roid) {
        //增加对应关系
        AgentUserSecRoleRel roleRole = getUserSecRoleRelByUid(uid);
        if (roleRole != null) {
            roleRole.setRoid(roid);
            roleRole.setUpdateTime(new Date());
            roleRole.setCreateTime(new Date());
            agentUserSecRoleRelDao.update(roleRole);
        } else {
            roleRole = new AgentUserSecRoleRel();
            roleRole.setRoid(roid);
            roleRole.setAgentUid(uid);
            roleRole.setState(1L);
            roleRole.setUpdateTime(new Date());
            roleRole.setCreateTime(new Date());
            agentUserSecRoleRelDao.save(roleRole);
        }
    }


    private AgentUserSecRoleRel getUserSecRoleRelByUid(Long uid) {
        String hql = "from AgentUserSecRoleRel where agentUid = :uid";
        HashMap params = new HashMap();
        params.put("uid", uid);
        List<AgentUserSecRoleRel> querBeans = agentUserSecRoleRelDao.find(hql, params);
        if (null != querBeans && querBeans.size() > 0) {
            return querBeans.get(0);
        }
        return null;
    }

    public List<AgentSecFunction> getUserEnableFunction(Long agentUid) {
        HashMap params = new HashMap();
        String hql = "";

        List<AgentSecFunction> secRoleFunctions = null;
        hql = "select b from AgentSecRoleFunction a , AgentSecFunction b, AgentUserSecRoleRel c " +
                "where  a.state=1 and b.state =1 and c.state = 1 and a.roid = c.roid and a.fid = b.fid and c.agentUid = :agentUid and b.funcType = 2";
        params.put("agentUid", agentUid);
        secRoleFunctions = agentSecFuncDao.find(hql, params);
        //获取一级菜单信息
        return secRoleFunctions;
    }
}
